﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace GDI_AnalysisComponents
{
    //创建连线
    public class CreateGLine
    {
        private int m_Step;
        private int MoveStop = 0;
        private PointF bpr, bpl;
        private PointF epr, epl;
        private GUnit preGUnit;
        private GUnit curGUnit;
        private PointF m_startPt, m_endPt;
        private PointF movePt, downPt; 

        public CreateGLine()
        {
        }

        //点击鼠标
        public string LButtonDown(Graphics g, PointF mousePt, GUnit gun, GGraph ggraph)
        {
            string s = null;
            downPt = mousePt;
            if (gun == null)
            {
                MoveStop = 0;
            }
            else
            {
                RectangleF rect = gun.getGUnitRect();
                float xr = rect.Right;
                float xl = rect.Left;
                float y = (rect.Top + rect.Bottom) / 2;

                //记录鼠标左键的单击次数
                m_Step += 1;
                switch (m_Step)
                {
                    //点击初始组件
                    case 1:
                        bpr = new PointF(xr, y);
                        bpl = new PointF(xl, y);
                        epr = bpr;
                        epl = bpl;
                        preGUnit = gun;
                        //GLine gl = ShortLine(bpr, bpl, mousePt, mousePt);
                        //gl.Draw(g);
                        //gl = null;
                        break;

                    //点击目标组件
                    case 2:
                        epr = new PointF(xr, y);
                        epl = new PointF(xl, y);
                        curGUnit = gun;

                        if (curGUnit.FartherGUnitID == -1 && curGUnit.Type == preGUnit.Type)
                        {
                            IntgunStack(ggraph, preGUnit);
                            s = FindHuiHuan(ggraph, curGUnit, preGUnit);
                        }
                        else if (curGUnit.Type != preGUnit.Type)
                            s = "类型不同，不能连！";
                        else if (curGUnit.FartherGUnitID != -1)
                            s = "此组件的参数已有输入！";
                        m_Step = 0;
                        MoveStop = 0;
                        break;
                }
            }
            return s;
        }

        //初始化GUnit栈
        public void IntgunStack(GGraph ggraph, GUnit findgun)
        {
            for (int i = 0; i < ggraph.GcSavs.Count; i++)
            {
                GComponent gc = (GComponent)(ggraph.GcSavs[i]);
                if (gc.ID == findgun.GComponentId)
                {
                    for (int j = 0; j < gc.ParaGUnitList.Count; j++)
                    {
                        GUnit tempgun = (GUnit)(gc.ParaGUnitList[j]);
                        ggraph.GunStack.Push(tempgun);
                    }
                }
            }
        }

        //查找回环，添加入度
        public string FindHuiHuan(GGraph ggraph, GUnit endgun, GUnit startgun)
        {
            string s = null;
            bool HASHUIHUAN = false;
            while (ggraph.GunStack.Count > 0)
            {
                GUnit gun = (GUnit)(ggraph.GunStack.Pop());
                //存在回环
                if (gun.GComponentId == endgun.GComponentId)
                {
                    HASHUIHUAN = true;
                    ggraph.GunStack.Clear();
                    break;
                }
                else if (gun.FartherGUnitID != -1 && gun.GComponentId != endgun.GComponentId)
                {
                    for (int i = 0; i < ggraph.GcSavs.Count; i++)
                    {
                        GComponent gc = (GComponent)(ggraph.GcSavs[i]);
                        for (int j = 0; j < gc.ParaGUnitList.Count; j++)
                        {
                            GUnit tempgun = (GUnit)(gc.ParaGUnitList[j]);
                            if (tempgun.ID == gun.FartherGUnitID)
                                IntgunStack(ggraph, tempgun);
                        }
                    }
                }
            }

            //没有回环，可连
            if (HASHUIHUAN == false)
            {
                endgun.FartherGUnitID = startgun.ID;
                for (int i = 0; i < ggraph.GcSavs.Count; i++)
                {
                    GComponent gc = (GComponent)(ggraph.GcSavs[i]);
                    if (gc.ID == endgun.GComponentId)
                    {
                        gc.InGunSList.Remove(startgun.GComponentId);
                        gc.InGunSList.Add(startgun.GComponentId);
                        GLinkGUnits glg = new GLinkGUnits(startgun, endgun);
                        ggraph.LineSavs.Add(glg);
                    }
                }
                s = "组件"+startgun.GComponentId+"的参数"+startgun.Name+"连接到组件"+endgun.GComponentId+"的参数"+endgun.Name;
            }
            else
                s = "存在回环不能连！";
            return s;
        }

        //画橡皮线，使用API的两画线相重时，图形消失的特性。
        public void MouseMove(Graphics g, PointF mousePt)
        {
            if (MoveStop == 0)
            {
                GLine gl = ShortLine(bpr, bpl, downPt, downPt);
                gl.Draw(g);
                gl = null;
                m_startPt = mousePt;
                m_endPt = mousePt;
            }
            if (MoveStop == 1)//消除多余直线
            {
                GLine Line = ShortLine(bpr, bpl, m_startPt, m_endPt);
                Line.Draw(g);
                Line = null;
            }
            MoveStop++;
            movePt = mousePt;
            PointF prePr = new PointF();
            PointF prePl = new PointF();
            PointF curPr = new PointF();
            PointF curPl = new PointF();

            prePr = epr;
            prePl = epl;
            curPr = mousePt;
            curPl = mousePt;

            GLine preLine = ShortLine(bpr, bpl, prePr, prePr);
            preLine.Draw(g);
            preLine = null;

            //绘当前位置的直线段
            GLine curLine = ShortLine(bpr, bpl, curPr, curPl);
            epr = curPr;
            epl = curPl;
            curLine.Draw(g);
            curLine = null;
        }

        //画连线算法，求最短距离
        public GLine ShortLine(PointF pr_1, PointF pl_1, PointF pr_2, PointF pl_2)
        {
            float x1, x2;
            float y1, y2;

            if (Math.Abs(pr_1.X - pr_2.X) > Math.Abs(pr_1.X - pl_2.X))
                x2 = pl_2.X;
            else
                x2 = pr_2.X;

            if (Math.Abs(pr_2.X - pr_1.X) > Math.Abs(pr_2.X - pl_1.X))
                x1 = pl_1.X;
            else
                x1 = pr_1.X;

            if (Math.Abs(pr_2.Y - bpr.Y) > Math.Abs(pr_2.Y - pl_1.Y))
                y1 = pl_1.Y;
            else
                y1 = pr_1.Y;

            if (Math.Abs(pr_1.Y - pr_2.Y) > Math.Abs(pr_1.Y - pl_2.Y))
                y2 = pl_2.Y;
            else
                y2 = pr_2.Y;

            PointF bp = new PointF(x1, y1);
            PointF ep = new PointF(x2, y2);
            GLine gl = new GLine(bp, ep);

            return gl;
        }

        //计算直线角度
        public double calculateAngle(PointF bp, PointF ep)
        {
            double xuelv = Math.Atan((ep.Y - bp.Y) / (ep.X - bp.X));
            double angle = 180 * xuelv / Math.PI;

            if (angle > 180)
                angle = angle + 180;

            if (bp.X > ep.X)
                angle = angle + 180;

            angle = angle + 180;

            return angle;
        }

        //绕定点旋转
        public Graphics rotateAngle(Graphics g, double angle, PointF pf)
        {
            Matrix mat = new Matrix();
            mat.RotateAt((float)angle, pf, MatrixOrder.Prepend);
            g.Transform = mat;
            return g;
        }

        //画箭头
        public void drawArrow(Graphics g, PointF pf)
        {
            float x1 = pf.X + 8;
            float y1 = pf.Y + 4;
            float x2 = pf.X + 8;
            float y2 = pf.Y - 4;
            PointF p1 = new PointF(x1, y1);
            PointF p2 = new PointF(x2, y2);
            Pen p = new Pen(Color.DeepPink, 1);
            g.DrawLine(p, pf, p1);
            g.DrawLine(p, pf, p2);
            g.DrawLine(p, p1, p2);

        }

    }
}
